/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月28日
 */
package com.massyframework.beanskin;

import java.util.Objects;

import com.massyframework.beanskin.util.version.VersionRange;

/**
 * 模块静态链接所依赖类库的说明。
 *
 * <p>
 * 模块之间存在两种依赖，最常见的是静态代码的链接依赖，maven中的dependency就是对静态依赖的声明。
 * 在beanskin中，需要在运行时解析模块运行的静态代码由哪个类库(模块)提供。通过RequireLibraryDescriptor可以
 * 指出这种模块静态代码的依赖关系。
 * </p>
 *
 * <p>
 * beanskin约定模块有四种类型，分被为library,plugin,assembly和fragment。
 * library是无入口方法的类库，需要共享的类仅允许做为library进行公开。
 * </p>
 *
 * @author huangkh
 */
public class RequireLibraryDescriptor {
	
	private String groupId;
	private String moduleId;
	private VersionRange versionRange;
	private final boolean transitive;

	/**
	 * 使用{@code builder}创建新实例
	 * @param builder {@link Builder},构建器
	 */
	protected RequireLibraryDescriptor(Builder builder) {
		this.groupId=Objects.requireNonNull(builder.groupId, "\"groupId\" cannot be null.");
		this.moduleId=Objects.requireNonNull(builder.moduleId, "\"moduleId\" cannot be null.");
		this.versionRange= builder.versionRange == null ?
    			VersionRange.valueOf("0.0.0"): builder.versionRange;
		this.transitive=builder.transitive;
	}

	/**
	 * library的组编号
	 * @return {@link String}
	 */
	public String getGroupId() {
		return groupId;
	}

	/**
	 * library的模块编号
	 * @return {@link String}
	 */
	public String getModuleId() {
		return moduleId;
	}

	/**
	 * library的版本范围
	 * @return {@link VersionRange}
	 */
	public VersionRange getVersionRange() {
		return versionRange;
	}

	/**
	 * 是否支持透传.
	 * <p>
	 * 模块A,B,C, 其中A依赖B，B依赖C.
	 * 如果，B对C依赖定义的透传为false, 那么，A无法加载C模块的类.
	 * 如果，B对C依赖定义的透传为true, 那么，A可以加载C模块的类.
	 * </p>
	 * @return {@link boolean},支持返回{@code true},否则返回{@code false}
	 */
	public boolean isTransitive() {
		return transitive;
	}
	
	/**
	 * 判断{@code identifier}所代表的类库，是否为所需依赖
	 * @param identifier {@link ModuleIdentifier},类库的标识符
	 * @return {@link boolean},返回{@code true}表示是所需依赖，否则返回{@code false}
	 */
	public boolean isRequire(ModuleIdentifier identifier) {
		if (identifier == null) return false;
		
		return this.getGroupId().equals(identifier.getGroupId())
				&& this.moduleId.equals(identifier.getModuleId())
				&& this.getVersionRange().includes(identifier.getVersion());
	}
	

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
		result = prime * result + ((moduleId == null) ? 0 : moduleId.hashCode());
		result = prime * result + ((versionRange == null) ? 0 : versionRange.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		RequireLibraryDescriptor other = (RequireLibraryDescriptor) obj;
		if (groupId == null) {
			if (other.groupId != null)
				return false;
		} else if (!groupId.equals(other.groupId))
			return false;
		if (moduleId == null) {
			if (other.moduleId != null)
				return false;
		} else if (!moduleId.equals(other.moduleId))
			return false;
		if (versionRange == null) {
			if (other.versionRange != null)
				return false;
		} else if (!versionRange.equals(other.versionRange))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "RequireLibraryDescriptor [groupId=" + groupId + ", moduleId=" + moduleId + ", versionRange=" + versionRange
				+ ", transitive=" + transitive + "]";
	}

	/**
	 * 创建构建器新实例
	 * @return {@link Builder}
	 */
	public static Builder newBuilder() {
		return new Builder();
	}

	/**
	 * 构建器
	 */
	public static class Builder {
		private String groupId;
		private String moduleId;
		private VersionRange versionRange;
		private boolean transitive = false;
		
		/**
		 * 设置组编号
		 * @param value {@link String}
		 * @return {@link Builder}
		 */
		public Builder groupId(String value) {
			this.groupId = value;
			return this;
		}
		
		/**
		 * 设置模块编号
		 * @param value {@link String}
		 * @return {@link Builder}
		 */
		public Builder moduleId(String value) {
			this.moduleId = value;
			return this;
		}
		
		/**
		 * 设置版本范围
		 * @param value {@link VersionRange}
		 * @return {@link Builder}
		 */
		public Builder versionRange(VersionRange value) {
			this.versionRange = value;
			return this;
		}
		
		/**
		 * 设置是否支持透传
		 * @param value {@link boolean}
		 * @return {@link Builder}
		 */
		public Builder transitive(boolean value) {
			this.transitive = value;
			return this;
		}
		
		/**
		 * 创建RequireModule实例
		 * @return {@link RequireLibraryDescriptor}
		 */
		public RequireLibraryDescriptor build() {
			return new RequireLibraryDescriptor(this);
		}
	}
}
